package base

import (
	"fmt"
	"jvm/nzpJvm/runtime_area"
	"jvm/nzpJvm/runtime_area/heap"
)

// 初始化类，就是调用类的clinit方法
func InitClass(thread *runtime_area.Thread, class *heap.Class) {	
	// 将状态标记为已经执行初始化
	class.StartInit() 
	// 为类初始化方法创建一个新的栈帧并压栈。
	scheduleClinit(thread, class)
	// 如果父类还没有被初始化，先进行父类的初始化。其实也是创建一个新的栈帧
	// 按以上的逻辑，如果父类还没初始化，生成的父类栈帧会在子类栈帧的上面，这意味着父类的clinit方法会比子类的clinit方法先执行
	initSuperClass(thread, class)
	fmt.Println("初始化类" + class.Name())
}

// 如果父类还没有被初始化，先进行初始化
func initSuperClass(thread *runtime_area.Thread, class *heap.Class) {
	if class.IsInterface() {
		// 接口没有clinit方法
		return
	}
	// 获取父类
	superClass := class.SuperClass()
	// 没有父类，不用初始化父类
	if superClass == nil {
		return
	}
	// 如果父类还没有被初始化，先进行初始化
	if !superClass.InitStart() {
		InitClass(thread, superClass)
	}
}

// 为类初始化方法创建一个新的栈帧并压栈。
func scheduleClinit(thread *runtime_area.Thread, class *heap.Class) {
	clinit := class.GetClinitMethod()
	if clinit != nil {
		// 为类初始化方法创建一个新的栈帧并压栈。
		clinitFrame := thread.NewFrame(clinit)
		thread.PushFrame(clinitFrame)
	}
}
